#include "MySDLWindow.h"
#include "Utils.h"


MySDLWindow::MySDLWindow(int width, int height, eMySDLFlags flags)
	: m_width(width)
	, m_height(height)
	, m_pMsg(nullptr)
	, m_bExit(false)
	, m_flags(MY_SDL_NONE)
{
	m_flags |= flags;
	m_pMsg = new YMessageList();
	m_pMsg->Init();
}

MySDLWindow::~MySDLWindow()
{
	if (m_pMsg)
	{
		m_pMsg->Release();
		delete m_pMsg;
		m_pMsg = nullptr;
	}
}

bool MySDLWindow::Init() {
	SDL_Init(SDL_INIT_EVERYTHING);
	m_pWndMain = SDL_CreateWindow("sdl_window", SDL_WINDOWPOS_CENTERED,
		SDL_WINDOWPOS_CENTERED, m_width, m_height, m_flags | SDL_WINDOW_RESIZABLE);
	if (!m_pWndMain)
		return false;

	m_pRenderer = SDL_CreateRenderer(m_pWndMain, -1, 0);
	if (!m_pRenderer)
		return false;

	m_pTexture = SDL_CreateTexture(m_pRenderer, SDL_PIXELFORMAT_IYUV,
		SDL_TEXTUREACCESS_STREAMING, m_width, m_height);
	if (!m_pTexture)
		return false;

	m_thead = SDL_CreateThread(&MySDLWindow::RefreshVideo, "sdl_thread", this);
	return true;
}

void MySDLWindow::DeInit()
{
	SDL_DestroyWindow(m_pWndMain);
	SDL_Quit();
}

void MySDLWindow::RenderYuv(uint8_t* data, int len)
{
	SDL_Rect  rect;
	rect.x = 0;
	rect.y = 0;
	rect.w = m_width;
	rect.h = m_height;
	SDL_UpdateTexture(m_pTexture, &rect, data, m_width);

	SDL_RenderClear(m_pRenderer);
	SDL_RenderCopy(m_pRenderer, m_pTexture, nullptr, &rect);
	SDL_RenderPresent(m_pRenderer);
	SDL_Delay(20);
}

void MySDLWindow::ProcessMessage()
{
	Init();
	while (!m_bExit)
	{
		SDL_Event event;

		if (!m_pMsg->IsEmpty())
		{
			std::lock_guard<std::mutex> guard(m_mutex);
			int len = m_pMsg->GetNextLength();
			uint8_t* data = new uint8_t[len];
			m_pMsg->GetData(data, len);

			SDL_WaitEvent(&event);
			switch (event.type)
			{
			case SFM_REFRESH_EVENT:
				RenderYuv(data, len);
				break;
			case SDL_KEYDOWN:
 				if (event.key.keysym.sym == SDLK_SPACE)
					m_thPause = !m_thPause;
				break;
			case SDL_QUIT: 
				m_thExit = 1;
				break;
			case SFM_BREAK_EVENT:
				m_bExit = 1;
				break;
			default:
				break;
			}
			delete[]data;
		}
	}
	DeInit();
}

void MySDLWindow::SendMessage(uint8_t * data, const size_t len)
{
	std::lock_guard<std::mutex> guard(m_mutex);
	m_pMsg->AddData(data, len);
}

int MySDLWindow::RefreshVideo(void *opaque) {
	MySDLWindow* pWnd = (MySDLWindow*)opaque;
	pWnd->m_thExit = 0;
	pWnd->m_thPause = 0;

	while (!pWnd->m_thExit) {
		if (!pWnd->m_thPause) {
			SDL_Event event;
			event.type = SFM_REFRESH_EVENT;
			SDL_PushEvent(&event);
		}
		SDL_Delay(20);
	}
	pWnd->m_thExit = 0;
	pWnd->m_thPause = 0;
	//Break
	SDL_Event event;
	event.type = SFM_BREAK_EVENT;
	SDL_PushEvent(&event);

	return 0;
}